<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>购物车</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        html,
        body {
            width: 100%;
            min-width: 1176px;
            min-height: 1200px;
            font-size: 16px;
            margin: auto;
            background-color: #F4F6FA;
            font-weight: 400;
            font-family: Helvetica, sans-serif;
        }

        #site-headline {
            padding-top: 2rem;
            background-image: linear-gradient(120deg, #b8daee 30%, rgb(29, 140, 252) 46%, #d2d7f8 70%);
            -webkit-background-clip: text;
            background-clip: text;
            -webkit-text-fill-color: transparent;
            font-size: 1.6rem;
            font-weight: 600;
            text-align: center;
            letter-spacing: .2rem;
        }

        table {
            width: 1200px;
            background-color: #fff;
            margin: 20px auto;
        }

        tr {
            margin-bottom: 10px;
        }

        td {
            padding: 10px;
            font-size: 16px;
            color: #333;
            border-bottom: 1px dashed #ddd;
        }

        .thead td {
            font-weight: 600;
        }

        .num button {
            width: 1.6rem;
            height: 1.6rem;
            color: #666;
            font-size: 1.4rem;
            text-align: center;
            line-height: 1.6rem;
            border: none;
        }

        .num input {
            height: 1.6rem;
            width: 3rem;
            text-align: center;
            color: #555;
            font-size: .9rem;
            border: 1px solid #ddd;
            position: relative;
            top: -2px;
            outline: none;
        }

        td span {
            color: #999;
            font-size: 13px;
        }

        .price {
            color: red;
            font-weight: 600;
        }

        input[type='checkbox'] {
            margin-right: 5px;
        }

        .del {
            font-weight: 600;
            color: brown;
            cursor: pointer;
        }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <h1 id="site-headline">Vue购物车结算</h1>
        <table>
            <tr class="thead">
                <td><label><input type="checkbox" v-model="isAllChecked" @change="checkAll">全选</label></td>
                <td colspan="3" align="right">单价(元)</td>
                <td align="center">数量</td>
                <td>小计(元)</td>
                <td style="cursor: pointer; color: skyblue;">编辑</td>
            </tr>
            <tr v-for="(shop, shopIndex) in shops" :key="shopIndex">
                <td colspan="7"><input type="checkbox" v-model="shop.isChecked" @change="checkShop(shopIndex)">
                    {{ shop.name }}</td>
            </tr>
            <tr v-for="(item, itemIndex) in allItems" :key="itemIndex">
                <td><input type="checkbox" v-model="item.isChecked" @change="checkItem(itemIndex)"></td>
                <td style="width: 120px;"><img width="100%" :src="item.image" alt="" /></td>
                <td>
                    {{ item.name }}<br>
                    <span>{{ item.desc }}</span>
                </td>
                <td class="price">￥{{ item.price.toFixed(2) }}</td>
                <td class="num">
                    <button @click="decrease(itemIndex)" :disabled="item.quantity <= 1">-</button>
                    <input type="text" v-model="item.quantity" @input="updateSubtotal(itemIndex)">
                    <button @click="increase(itemIndex)">+</button>
                </td>
                <td class="price">￥{{ item.subtotal.toFixed(2) }}</td>
                <td>-</td>
            </tr>
            <tr>
                <td><label><input type="checkbox" v-model="isAllChecked" @change="checkAll">全选</label></td>
                <td class="del" @click="deleteSelected">删除选中商品</td>
                <td>共有 {{ totalItems }} 件商品,已选择 <b>{{ selectedItems }}</b> 件</td>
                <td align="right" colspan="4">合计： <b class="price" style="font-size: 18px;">￥{{ totalPrice.toFixed(2) }}</b></td>
            </tr>
        </table>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                shops: [
                    { name: '店铺1', isChecked: false },
                    { name: '店铺2', isChecked: false }
                ],
                allItems: [
                    {
                        shopIndex: 0,
                        name: 'MEIZU UR 高端定制耳机',
                        desc: '十单元 8699起',
                        price: 8699,
                        quantity: 1,
                        subtotal: 8699,
                        isChecked: false,
                        image: 'images/p1.png'
                    },
                    {
                        shopIndex: 1,
                        name: 'MEIZU UR 高端定制耳机',
                        desc: '十单元 8699起',
                        price: 8699,
                        quantity: 1,
                        subtotal: 8699,
                        isChecked: false,
                        image: 'images/p2.png'
                    }
                ]
            },
            computed: {
                isAllChecked: {
                    get() {
                        return this.allItems.every(item => item.isChecked);
                    },
                    set(newValue) {
                        this.allItems.forEach(item => item.isChecked = newValue);
                        this.shops.forEach(shop => shop.isChecked = newValue);
                    }
                },
                totalItems() {
                    return this.allItems.reduce((total, item) => total + item.quantity, 0);
                },
                selectedItems() {
                    return this.allItems.filter(item => item.isChecked).reduce((total, item) => total + item.quantity, 0);
                },
                totalPrice() {
                    return this.allItems.filter(item => item.isChecked).reduce((total, item) => total + item.subtotal, 0);
                }
            },
            methods: {
                checkAll() {
                    this.allItems.forEach(item => item.isChecked = this.isAllChecked);
                    this.shops.forEach(shop => shop.isChecked = this.isAllChecked);
                },
                checkShop(shopIndex) {
                    const isChecked = this.shops[shopIndex].isChecked;
                    this.allItems.forEach(item => {
                        if (item.shopIndex === shopIndex) {
                            item.isChecked = isChecked;
                        }
                    });
                },
                checkItem(itemIndex) {
                    const item = this.allItems[itemIndex];
                    const shop = this.shops[item.shopIndex];
                    const shopItems = this.allItems.filter(i => i.shopIndex === item.shopIndex);
                    shop.isChecked = shopItems.every(i => i.isChecked);
                },
                decrease(itemIndex) {
                    if (this.allItems[itemIndex].quantity > 1) {
                        this.allItems[itemIndex].quantity--;
                        this.updateSubtotal(itemIndex);
                    }
                },
                increase(itemIndex) {
                    this.allItems[itemIndex].quantity++;
                    this.updateSubtotal(itemIndex);
                },
                updateSubtotal(itemIndex) {
                    const item = this.allItems[itemIndex];
                    item.subtotal = item.price * item.quantity;
                },
                deleteSelected() {
                    this.allItems = this.allItems.filter(item => !item.isChecked);
                }
            }
        });
    </script>
</body>

</html>